/**
 * @file filter
 * @author liaoxuezhi@baidu.com
 */
/* eslint fecs-indent: [0, "space", 2, 2] */

import * as React from 'react';
import {
  Component,
  PropTypes
} from 'react';
import {Renderer, filter} from './renderer';
import OnExpression from './hoc/on-expression';
import Iframe from '../widgets/iframe.jsx';
import * as cx from 'classnames';
import * as assign from 'object-assign';
import {Enhance as FormItem} from './form/form-item';
import {buildApi} from './util';
import * as qs from 'qs';
import * as isPlainObject from 'lodash/isPlainObject';

@FormItem({
  type: 'iframe',
  haveAllElements: false,
  test: (path, config) => /(?:^|\/)iframe$/.test(path)
  || /(?:^|\/)form-item$/.test(path) && ~['iframe'].indexOf(config.type)
})
export default class IframeRenderer extends Component {
  static propTypes = {
    className: PropTypes.string,
    src: PropTypes.oneOfType([
      PropTypes.string,
      PropTypes.shape({
        url: PropTypes.string.isRequired,
        data: PropTypes.object
      })
    ]).isRequired,
    attachData: PropTypes.bool
  };

  static defaultProps = {
    html: '',
    attachData: false
  };

  constructor(props) {
    super(props);

    this.state = {
      src: props.src,
      initialSourceFetched: false
    };

    this.buildSrc = this.buildSrc.bind(this);
  }

  componentDidMount() {
    const {
      src,
      isReady/*,
      value*/
    } = this.props;

    src && (typeof isReady === 'undefined' || isReady) && this.setState({
      src: this.buildSrc(this.props),
      initialSourceFetched: true
    });

    /*if (typeof value === 'string' && value.indexOf('$')) {
      this.setValue(tokenize(value, data));
    }*/
  }

  componentWillReceiveProps(nextProps) {
    const props = this.props;
    if (
      !this.state.initialSourceFetched
      && nextProps.src
      && props.data !== nextProps.data
      && nextProps.isReady
    ) {
      this.setState({
        src: this.buildSrc(props),
        initialSourceFetched: true
      });
    } else if (props.src && /\$|<%/.test(props.src) || nextProps.src && /\$|<%/.test(nextProps.src)) {
      const prevSource = filter(props.src, props.data);
      const nextSource = filter(nextProps.src, nextProps.data);

      if (prevSource !== nextSource) {
        this.setState({
          initialSourceFetched: true,
          src: this.buildSrc(nextProps)
        });
      }
    } else if (
      props.src && props.src.url && /\$|<%/.test(props.src.url)
      || nextProps.src && nextProps.src.url && /\$|<%/.test(nextProps.src.url)
    ) {
      const prevSource = filter(props.src.url, props.data);
      const nextSource = filter(nextProps.src.url, nextProps.data);

      if (prevSource !== nextSource) {
        this.setState({
          initialSourceFetched: true,
          src: this.buildSrc(nextProps)
        });
      }
    }
  }

  buildSrc(props) {
    let src = props.src;
    let url;
    if (typeof src == 'string') {
      src = {
        url: src
      }
    }
    url = src.url;

    src = assign({}, src, {method: 'get'});

    let api = buildApi(src, props.data, 'get', {}, true);

    let data = assign({}, api.data || {});
    api.appended || isPlainObject(props.data) && props.attachData && assign(data, props.data);

    const idx = api.url.indexOf('?');
    const endIdx = api.url.lastIndexOf('#');
    const end = ~endIdx ? endIdx : api.url.length;

    if (~idx) {
      const params = qs.parse(api.url.substring(idx + 1, end));
      url = api.url.substring(0, idx);
      assign(data, params);
    }

    let strParams = qs.stringify(data, {arrayFormat: 'brackets', encode: false});
    src = url + '?' + strParams + api.url.substring(end);

    return src;
  }

  reload() {
    const input = this.input;
    const {
      src,
      data
    } = this.props;
    let newSrc = src;

    if (src) {
      newSrc = this.buildSrc(this.props);
      this.setState({
        src: newSrc
      });
    }
  }

  render() {
    const {
      formMode,
      inline,
      className,
      src,
      style,
      data,
      width,
      height
    } = this.props;

    return (
      <div
        className={cx(className, {
          'inline m-l-xs': inline || formMode === 'inline'
        })}
        style={style}
      >
        <Iframe
          src={this.state.src}
          width={width}
          height={height}
        ></Iframe>
      </div>
    );
  }
}
